package com.kuang.saleTicket;

/**
 *  基本的卖票例子   不使用JUC（java.util.concurrent.locks  三个接口： 1.Condition 2.Lock 3.ReadWriteLock）
 *
 * @author sdm
 * @version 1.0
 * @date 2023/6/19 17:27
 */
public class SaleTicketDemo01 {
    // 1. 准备资源类（属性、方法（sychnorized加锁，本质：队列、锁），对共享资源加锁，控制并发）
    // 2. 创建多线程
    // 3. 将资源类抛进去
    // 参考文章：Java线程池的正确使用方式——不要再new Thread了 http://t.csdn.cn/ytpMd
    public static void main(String[] args) {

        Ticket ticket = new Ticket(); // 并发：多线程操作同一资源类，将资源类丢入线程

        new Thread().start();
        new Thread(new Runnable() {  // @FunctionalInterface 函数式接口
            public void run() {
                // 匿名内部类，new Runnable(重写run方法)
            }
        }).start();
        new Thread(()->{ }, "线程名").start(); // jdk1.8之后，简化为Lambda表达式


        // 三个线程操作同一资源，三个线程同时卖票
        new Thread(()->{ for (int i = 0; i < 10; i++) { ticket.sale();}}, "A").start(); // 线程A卖60次
        new Thread(()->{ for (int i = 0; i < 10; i++) { ticket.sale();}}, "B").start(); // 线程B卖60次
        new Thread(()->{ for (int i = 0; i < 10; i++) { ticket.sale();}}, "C").start(); // 线程C卖60次
        // 期望出现结果：
        /*
            A卖出了第30票，剩余：29
            A卖出了第29票，剩余：28
            A卖出了第28票，剩余：27
            A卖出了第27票，剩余：26
            A卖出了第26票，剩余：25
            A卖出了第25票，剩余：24
            A卖出了第24票，剩余：23
            A卖出了第23票，剩余：22
            A卖出了第22票，剩余：21
            A卖出了第21票，剩余：20
            B卖出了第20票，剩余：19
            B卖出了第19票，剩余：18
            B卖出了第18票，剩余：17
            B卖出了第17票，剩余：16
            B卖出了第16票，剩余：15
            B卖出了第15票，剩余：14
            B卖出了第14票，剩余：13
            B卖出了第13票，剩余：12
            B卖出了第12票，剩余：11
            B卖出了第11票，剩余：10
            B卖出了第10票，剩余：9
            B卖出了第9票，剩余：8
            B卖出了第8票，剩余：7
            B卖出了第7票，剩余：6
            B卖出了第6票，剩余：5
            C卖出了第5票，剩余：4
            C卖出了第4票，剩余：3
            C卖出了第3票，剩余：2
            C卖出了第2票，剩余：1
            C卖出了第1票，剩余：0
        */

        // 实际出现结果， 买票方法需要加锁，排队   public synchronized void sale()
        /*
            A卖出了第30票，剩余：29
            A卖出了第29票，剩余：28
            A卖出了第28票，剩余：27
            B卖出了第27票，剩余：26
            A卖出了第26票，剩余：25
            B卖出了第25票，剩余：24
            A卖出了第24票，剩余：23
            B卖出了第23票，剩余：22
            A卖出了第22票，剩余：21
            B卖出了第21票，剩余：20
            A卖出了第20票，剩余：19
            B卖出了第19票，剩余：18
            A卖出了第18票，剩余：17
            B卖出了第17票，剩余：16
            A卖出了第16票，剩余：15
            C卖出了第14票，剩余：13
            C卖出了第12票，剩余：11
            C卖出了第11票，剩余：10
            C卖出了第10票，剩余：9
            C卖出了第9票，剩余：8
            C卖出了第8票，剩余：7
            C卖出了第7票，剩余：6
            C卖出了第6票，剩余：5
            C卖出了第5票，剩余：4
            B卖出了第15票，剩余：14
            C卖出了第4票，剩余：3
            A卖出了第13票，剩余：12
            B卖出了第3票，剩余：2
            B卖出了第2票，剩余：1
            B卖出了第1票，剩余：0
         */

    }
}

// 资源类OOP   属性+方法
class Ticket {
    // 票数
    private int number = 30;

    // 卖票：每卖一次，票数减一
    public synchronized void sale(){  // 方式1： synchronized锁同步方法

        //synchronized (this){ // 方式2： synchronized锁同步代码块    this就是public synchronized void sale()里的 synchronized
        //
        //}
        //synchronized (Ticket.class){ // 方式2： synchronized锁同步代码块    保证Ticket模板只有一个
        //
        //}
        if (number > 0){
            System.out.println(Thread.currentThread().getName() + "卖出了第" + (number--) + "票，剩余：" + number);
        }
    }
}
